package main

import (
	"context"
	"demo/grpc/proto"
	"fmt"
	"io"
	"log"
	"math/rand"
	"net"
	"strconv"
	"time"

	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/status"

	"google.golang.org/grpc"
)

/**
client  --1--->   server
client  <--2---   server
*/
type UserServer struct{}

func (Service *UserServer) SaveUser(ctx context.Context, params *proto.UserParams) (*proto.Id, error) {
	time.Sleep(3 * time.Second)

	// 检测是否超时
	/*timeD, ok := ctx.Deadline()
	if ok {
		fmt.Println(timeD.Format("2006-01-02 15:04:05"), ctx.Err())
		return nil, status.Errorf(codes.Canceled, "UserServer.SaveUser Deadline")
	}*/

	select {
	case <-ctx.Done():
		fmt.Println("ctx.Done", ctx.Err())
		return nil, status.Errorf(codes.Canceled, "UserServer.SaveUser Deadline")
	}

	id := rand.Int31n(100)
	res := &proto.Id{Id: id}
	fmt.Printf("%+v", params.GetAge())
	fmt.Printf("%+v\n", params.GetName())
	return res, nil
}

func (Service *UserServer) GetUserInfo(ctx context.Context, id *proto.Id) (*proto.UserInfo, error) {
	res := &proto.UserInfo{Id: id.GetId(), Name: "test", Age: 31}
	return res, nil
}

/**
client  -1-> -2-> -3-> -4-> server
client  <--------1---------- server
*/
type StreamArticleServer struct{}

func (server *StreamArticleServer) SaveArticle(stream proto.ArticleServer_SaveArticleServer) error {
	for {
		id := rand.Int31n(100)
		r, err := stream.Recv()
		if err == io.EOF {
			fmt.Printf("读取数据结束")
			res := &proto.Aid{Id: id}
			return stream.SendAndClose(res)
		}

		if err != nil {
			return err
		}

		fmt.Printf("stream.rev author: %s, title: %s, content: %s\n", r.Author.GetAuthor(), r.Title.GetTitle(), r.Content.GetContent())
	}
}

/**
client  ----1------------------>  server
client  <-5- <-4- <-3- <-2- <-1-  server
*/
func (server *StreamArticleServer) GetArticleInfo(aid *proto.Aid, stream proto.ArticleServer_GetArticleInfoServer) error {
	for i := 0; i < 6; i++ {
		id := strconv.Itoa(int(aid.GetId()))
		err := stream.Send(&proto.ArticleInfo{
			Id:      aid.GetId(),
			Author:  "jack",
			Title:   "title_go_" + id,
			Content: "content_go_" + id,
		})
		if err != nil {
			return err
		}
	}
	fmt.Printf("发送完毕")
	return nil
}

/**
client  -1-> -2-> -3-> --4> -5-> server
client  <-5- <-4- <-3- <-2- <-1-  server
*/
// 双端
func (server *StreamArticleServer) DeleteArticle(stream proto.ArticleServer_DeleteArticleServer) error {
	for {
		// 接收client发送的流数据
		r, err := stream.Recv()
		if err == io.EOF {
			fmt.Println("read done!")
			return nil
		}

		if err != nil {
			return err
		}
		fmt.Printf("stream.rev aid:%d\n", r.GetId())

		// 发流数据给client
		err = stream.Send(&proto.Status{Code: true})
		if err != nil {
			return err
		}
	}
}

func main() {
	// 读2个证书
	/*c, err := credentials.NewServerTLSFromFile("./test.pem", "./test.key")
	if err != nil {
		log.Fatalf("new tls server err:%v", err.Error())
	}*/
	// 监听
	listen, err := net.Listen("tcp", "127.0.0.1:9527")
	if err != nil {
		log.Fatalf("tcp listen failed:%v", err)
	}
	// 创建grpc服务
	server := grpc.NewServer()
	//server := grpc.NewServer(grpc.Creds(c))

	// 注册服务
	proto.RegisterUserServerServer(server, &UserServer{})
	fmt.Println("userServer grpc services start success")

	proto.RegisterArticleServerServer(server, &StreamArticleServer{})
	fmt.Println("article stream server grpc services start success")

	_ = server.Serve(listen)
}
